<?php
class MineService extends AbstractService
{
    /**
     * @var MineService
     */
    private static $instance;

    /**
     * 单例函数
     * @return MineService
     */
    public static function get()
    {
        if (!self::$instance) {
            self::$instance = new MineService();
        }
        return self::$instance;
    }


    /**
     * 处理创建时的逻辑
     *
     * @param int $shardId
     * @return void
     */
    public function handleCreate($shardId)
    {

    }

    /**
     * 处理用户登录时的逻辑
     * 1. 登录游戏时候发送排行
     *
     * @param int $userId
     * @return void
     */
    public function handleLogin($userId)
    {

    }

    /**
     * 提供当前 service 数据
     *
     * @param int $userId
     * @param boolean $visitMode default false
     * @return array(MineVoList)
     */
    public function info($userId, $visitMode = false)
    {
        $mineList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_MINE);
        return array(
            $mineList
        );
    }

    /**
     * 矿洞开采
     *
     * @param int $userId
     * @param int $gridId
     * @param int $gridLayer
     * @param int $requireId
     * @throws SzException
     * @return MineVo
     */
    public function mine($userId, $gridId, $gridLayer, $requireId)
    {
        /**
         * @var BuildingVo $building
         */
        list($decorId, $building) = BuildingService::get()->getGroundAndDecorRecord($userId, $gridId, $gridLayer);
        $buildingDefId = $building->getBuildingDefId();

        $mineSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_BUILDING_MINE, $buildingDefId, true);
        $mineDropSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_BUILDING_MINE_DROP, $requireId, true);

        // 判断矿洞产物配置是否存在
        if (!in_array($requireId, $mineSetting['mineId'])) {
            throw new SzException(21501, array($requireId, $buildingDefId));
        }

        // 判断矿洞产物配置id的等级是否达到
        if ($mineSetting['unlockLevel'][array_search($requireId, $mineSetting['mineId'])] > UserService::get()->getUserLevel($userId)) {
            throw new SzException(21502, array($requireId));
        }

        /**
         * @var MineVoList $mineList
         * @var MineVo $mine
         */
        $mineList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_MINE);
        $mine = $mineList->getElement($userId, false);

        if (!$mine) {
            $mine = new MineVo(
                $userId,
                GameConst::DEFAULT_JSON_STRING,
                -1,
                0,
                true
            );
        }

        // 说明当前矿洞正在处理开采
        if ($mine->getRequireId() != -1) {
            return $mine;
        }

        // 扣除矿洞开采的消耗
        GameService::get()->handleEntity($userId, $mineDropSetting['requireId'], $mineDropSetting['cost'], true);
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_MINE_FUNC,$userId,0,$mineDropSetting['requireId'].':'.$mineDropSetting['cost'].'|','mine');//消耗资源上报

        // 计算矿洞开采随机掉落次数
        $droppingCount = rand(1, $mineDropSetting['dropCountLimit']);

        $drops = [];
        for ($i = 0; $i < $droppingCount; $i++) {
            $itemDefId = SzUtility::getRandomElementByProbability($mineDropSetting['dropItem']);
            if (!SzUtility::checkArrayKey($itemDefId, $drops)) {
                $drops[$itemDefId] = 1;
            } else {
                $drops[$itemDefId]+= 1;
            }
        }

        // 更新矿洞数据
        $mine->setRequireId($requireId);
        $mine->setDrop($drops);
        $mine->setExp($mineDropSetting['exp'] * $droppingCount);

        if ($mine->isInsert() && !SzUtility::checkArrayKey($userId, $mineList->getList())) {
            $mineList->addElement($mine);
            $mineList->setElement($userId, $mine);
        } else {
            $mineList->updateElement($userId, $mine);
        }

        SzPersister::get()->setVoList($mineList);

        // 数据采集:矿场采矿
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:Mine|action:exploitation|',
                'item' => $requireId,
                'value' => 1
            )
        ));

        // 数据采集:矿场采矿消耗
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_INPUT, array(
            'clientData' => array(
                'tid' => $mineDropSetting['requireId']. ':' . abs($mineDropSetting['cost']) . '|',
                'item' => 'Mine_exploitation_' . $requireId
            )
        ));

        return $mine;
    }

    /**
     * 矿洞开采收矿
     *
     * @param int $userId
     * @throws SzException
     * @return boolean
     */
    public function receive($userId)
    {
        /**
         * @var MineVoList $mineList
         * @var MineVo $mine
         */
        $mineList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_MINE);
        $mine = $mineList->getElement($userId, false);

        if (!$mine || $mine->getRequireId() == -1) {
            throw new SzException(21503);
        }
        $requireId = $mine->getRequireId();

        // 获得奖励
        $outputTid = '';
        foreach ($mine->getRawDrop() as $dropId => $count) {
            GameService::get()->handleEntity($userId, $dropId, $count, true, true);
            $outputTid .= $dropId . ':' . $count . '|';
        }
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_MINE_FUNC,$userId,1,$outputTid,'receive');//获得资源上报

        // 获得经验
        GameService::get()->handleEntity($userId, GameConst::ENTITY_ACTION_GET_EXP, $mine->getExp(), true);
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_MINE_FUNC,$userId,1,GameConst::ENTITY_ACTION_GET_EXP.':'.$mine->getExp().'|','receive');//获得资源上报

        // 更新矿洞数据
        $mine->setRequireId(-1);
        $mine->setDrop(array());
        $mineList->updateElement($userId, $mine);

        SzPersister::get()->setVoList($mineList);

        // 数据采集:矿场采矿产出物领取
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:Mine|action:claim|',
                'item' => $requireId,
                'value' => 1
            )
        ));

        // 数据采集:矿场采矿产出物领取产出
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
            'clientData' => array(
                'tid' => $outputTid,
                'item' => 'Mine_claim'
            )
        ));

        return true;
    }
}